"use strict";
jQuery.base64 = (function($) {
	var _PADCHAR = "=",
		_ALPHA = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",
		_VERSION = "1.0";

	function _getbyte64(s, i) {
		var idx = _ALPHA.indexOf(s.charAt(i));
		if (idx === -1) {
			throw "Cannot decode base64"
		}
		return idx
	}

	// function _decode(s) {
	// 	var pads = 0,
	// 		i, b10, imax = s.length,
	// 		x = [];
	// 	s = String(s);
	// 	if (imax === 0) {
	// 		return s
	// 	}
	// 	if (imax % 4 !== 0) {
	// 		throw "Cannot decode base64"
	// 	}
	// 	if (s.charAt(imax - 1) === _PADCHAR) {
	// 		pads = 1;
	// 		if (s.charAt(imax - 2) === _PADCHAR) {
	// 			pads = 2
	// 		}
	// 		imax -= 4
	// 	}
	// 	for (i = 0; i < imax; i += 4) {
	// 		b10 = (_getbyte64(s, i) << 18) | (_getbyte64(s, i + 1) << 12) | (_getbyte64(s, i + 2) << 6) |
	// 			_getbyte64(s, i + 3);
	// 		x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 255, b10 & 255))
	// 	}
	// 	switch (pads) {
	// 		case 1:
	// 			b10 = (_getbyte64(s, i) << 18) | (_getbyte64(s, i + 1) << 12) | (_getbyte64(s, i + 2) << 6);
	// 			x.push(String.fromCharCode(b10 >> 16, (b10 >> 8) & 255));
	// 			break;
	// 		case 2:
	// 			b10 = (_getbyte64(s, i) << 18) | (_getbyte64(s, i + 1) << 12);
	// 			x.push(String.fromCharCode(b10 >> 16));
	// 			break
	// 	}
	// 	return x.join("")
	// }
	
	/**
	 * base64解码
	 */
	function _decode(str) {
		var c1, c2, c3, c4;
		var i, len, out;
		len = str.length;
		i = 0;
		out = "";
		while (i < len) {
			/* c1 */
			do {
				c1 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
			}
			while (i < len && c1 == -1);
			if (c1 == -1)
				break;
			/* c2 */
			do {
				c2 = base64DecodeChars[str.charCodeAt(i++) & 0xff];
			}
			while (i < len && c2 == -1);
			if (c2 == -1)
				break;
			out += String.fromCharCode((c1 << 2) | ((c2 & 0x30) >> 4));
			/* c3 */
			do {
				c3 = str.charCodeAt(i++) & 0xff;
				if (c3 == 61)
					return out;
				c3 = base64DecodeChars[c3];
			}
			while (i < len && c3 == -1);
			if (c3 == -1)
				break;
			out += String.fromCharCode(((c2 & 0XF) << 4) | ((c3 & 0x3C) >> 2));
			/* c4 */
			do {
				c4 = str.charCodeAt(i++) & 0xff;
				if (c4 == 61)
					return out;
				c4 = base64DecodeChars[c4];
			}
			while (i < len && c4 == -1);
			if (c4 == -1)
				break;
			out += String.fromCharCode(((c3 & 0x03) << 6) | c4);
		}
		return out;
	}

	function _getbyte(s, i) {
		var x = s.charCodeAt(i);
		if (x > 255) {
			throw "INVALID_CHARACTER_ERR: DOM Exception 5"
		}
		return x
	}

	function _encode(s) {
		if (arguments.length !== 1) {
			throw "SyntaxError: exactly one argument required"
		}
		s = String(s);
		var i, b10, x = [],
			imax = s.length - s.length % 3;
		if (s.length === 0) {
			return s
		}
		for (i = 0; i < imax; i += 3) {
			b10 = (_getbyte(s, i) << 16) | (_getbyte(s, i + 1) << 8) | _getbyte(s, i + 2);
			x.push(_ALPHA.charAt(b10 >> 18));
			x.push(_ALPHA.charAt((b10 >> 12) & 63));
			x.push(_ALPHA.charAt((b10 >> 6) & 63));
			x.push(_ALPHA.charAt(b10 & 63))
		}
		switch (s.length - imax) {
			case 1:
				b10 = _getbyte(s, i) << 16;
				x.push(_ALPHA.charAt(b10 >> 18) + _ALPHA.charAt((b10 >> 12) & 63) + _PADCHAR + _PADCHAR);
				break;
			case 2:
				b10 = (_getbyte(s, i) << 16) | (_getbyte(s, i + 1) << 8);
				x.push(_ALPHA.charAt(b10 >> 18) + _ALPHA.charAt((b10 >> 12) & 63) + _ALPHA.charAt((b10 >> 6) &
					63) + _PADCHAR);
				break
		}
		return x.join("")
	}
	return {
		decode: _decode,
		encode: _encode,
		VERSION: _VERSION
	}
}(jQuery));
